package logging_test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"testing"
	"v8s-controller/internal/db"
	"v8s-controller/internal/logging"

	"github.com/opensearch-project/opensearch-go"

	"github.com/stretchr/testify/require"
)

type (
	LoggingSuit struct {
		Folder string
	}
)

func TestCreate(t *testing.T, suit LoggingSuit) {
	input, err := ioutil.ReadFile("logging/" + suit.Folder + "/fixture-mongodb.json")
	if err != nil {
		t.Fatalf("failed to read input: %s", err)
	}

	var task db.Task
	if err := json.Unmarshal(input, &task); err != nil {
		t.Fatalf("failed to unmarshall input: %s", err)
	}
	client := &opensearch.Client{}

	lR := logging.CreateLoggingRepository(client)
	roleName := task.RN.ToIsolationContext().StringWithDelimeter('-')
	indexAlias := []logging.LoggingIndexAlias{{Index: fmt.Sprintf("%s-%s*", task.RN.StringWithDelimeter('-'), "service"),
		Alias: fmt.Sprintf("%s_%s", task.TN, "service")}}
	indexPatterns := make([]string, 0)
	for _, ia := range indexAlias {
		indexPatterns = append(indexPatterns, ia.Index)
	}
	cred := db.LoggingCredentials{User: "user", Password: "password"}
	indexPatternsToCreate := make([]*logging.LoggingRequest, 0)
	requestCreateRole := lR.CreateRole(roleName, indexPatterns)
	requestCreateUser := lR.CreateUser(cred.User, cred.Password)
	requestCreateMapRole := lR.MapUserRole(cred.User, roleName)
	//TODO: Aliases
	//requestCreateAliases := lR.CreateAliases(indexAlias)
	for _, ia := range indexAlias {
		indexPatternsToCreate = append(indexPatternsToCreate, &lR.CreateIndexPattern(ia.Alias, "time", client).LR)
	}
	//TODO: Aliases
	//checkLoginRequest(t, "logging/"+suit.Folder+"/expected-alias.json", requestCreateAliases)
	checkLoginRequests(t, "logging/"+suit.Folder+"/expected-indexes.json", indexPatternsToCreate)
	checkLoginRequest(t, "logging/"+suit.Folder+"/expected-role.json", requestCreateRole)
	checkLoginRequest(t, "logging/"+suit.Folder+"/expected-user.json", requestCreateUser)
	checkLoginRequest(t, "logging/"+suit.Folder+"/expected-map.json", requestCreateMapRole)
}

func TestPatch(t *testing.T, suit LoggingSuit) {

	input, err := ioutil.ReadFile("logging/" + suit.Folder + "/fixture-mongodb.json")
	if err != nil {
		t.Fatalf("failed to read input: %s", err)
	}

	var task db.Task
	if err := json.Unmarshal(input, &task); err != nil {
		t.Fatalf("failed to unmarshall input: %s", err)
	}
	client := &opensearch.Client{}

	lR := logging.CreateLoggingRepository(client)
	roleName := task.RN.ToIsolationContext().StringWithDelimeter('-')
	indexAlias := []logging.LoggingIndexAlias{{Index: fmt.Sprintf("%s-%s*", task.RN.StringWithDelimeter('-'), "service"),
		Alias: fmt.Sprintf("%s_%s", task.TN, "service")}}
	indexPatterns := make([]string, 0)
	for _, ia := range indexAlias {
		indexPatterns = append(indexPatterns, ia.Index)
	}
	indexPatternsToCreate := make([]*logging.LoggingRequest, 0)
	requestCreateRole := lR.UpdateRole(roleName, indexPatterns)
	//TODO: Aliases
	//requestCreateAliases := lR.CreateAliases(indexAlias)
	for _, ia := range indexAlias {
		indexPatternsToCreate = append(indexPatternsToCreate, &lR.CreateIndexPattern(ia.Alias, "time", client).LR)
	}
	//TODO: Aliases
	//checkLoginRequest(t, "logging/"+suit.Folder+"/expected-alias.json", requestCreateAliases)
	checkLoginRequests(t, "logging/"+suit.Folder+"/expected-indexes.json", indexPatternsToCreate)
	checkLoginRequest(t, "logging/"+suit.Folder+"/expected-role.json", requestCreateRole)
}

func checkLoginRequest(t *testing.T, file string, loginRequest *logging.LoggingRequestResult) {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		panic(fmt.Errorf("failed to open file '%s': %w", file, err))
	}

	actual, err := json.MarshalIndent(loginRequest.LR, "", "  ")
	if err != nil {
		panic(fmt.Errorf("failed to marshall documents: %w", err))
	}

	require.JSONEq(t, string(data), string(actual))

}

func checkLoginRequests(t *testing.T, file string, loginRequests []*logging.LoggingRequest) {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		panic(fmt.Errorf("failed to open file '%s': %w", file, err))
	}

	actual, err := json.MarshalIndent(loginRequests, "", "  ")
	if err != nil {
		panic(fmt.Errorf("failed to marshall documents: %w", err))
	}

	require.JSONEq(t, string(data), string(actual))

}
